package com.mall.project.ma.service.impl;

import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mall.common.core.asserts.ApiAssert;
import com.mall.common.core.enums.ErrorCodeEnum;
import com.mall.common.redis.utils.RedisUtils;
import com.mall.common.wxMa.config.WxMaConfiguration;
import com.mall.project.ma.cons.WxCons;
import com.mall.project.ma.mapper.WxUserMapper;
import com.mall.project.ma.model.dto.ThirdSession;
import com.mall.project.ma.model.entity.WxUser;
import com.mall.project.ma.service.IWxUserService;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 微信用户 服务实现类
 * </p>
 *
 * @author Sam
 * @since 2021-09-28
 */
@Service
public class WxUserServiceImpl extends ServiceImpl<WxUserMapper, WxUser> implements IWxUserService {

    @Autowired
    private RedisUtils redisUtils;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WxUser loginMa(String appId, String jsCode) throws WxErrorException {
        WxMaJscode2SessionResult jscode2session = WxMaConfiguration.getMaService(appId).jsCode2SessionInfo(jsCode);
        WxUser wxUser = this.getByOpenId(jscode2session.getOpenid());
        if (wxUser == null) {
            //新增微信用户
            wxUser = new WxUser();
            wxUser.setAppType(WxCons.WX_APP_TYPE_MINI);
            wxUser.setOpenId(jscode2session.getOpenid());
            wxUser.setSessionKey(jscode2session.getSessionKey());
            wxUser.setUnionId(jscode2session.getUnionid());
            try {
                this.save(wxUser);
            } catch (DuplicateKeyException e) {
                if (e.getMessage().contains("uk_appid_openid")) {
                    wxUser = this.getByOpenId(wxUser.getOpenId());
                }
            }
        } else {
            //更新SessionKey
            wxUser.setAppType(WxCons.WX_APP_TYPE_MINI);
            wxUser.setOpenId(jscode2session.getOpenid());
            wxUser.setSessionKey(jscode2session.getSessionKey());
            wxUser.setUnionId(jscode2session.getUnionid());
            this.updateById(wxUser);
        }

        String thirdSessionKey = UUID.randomUUID().toString();
        ThirdSession thirdSession = new ThirdSession();
        thirdSession.setAppId(appId);
        thirdSession.setSessionKey(wxUser.getSessionKey());
        thirdSession.setWxUserId(wxUser.getId());
        thirdSession.setOpenId(wxUser.getOpenId());
        //将3rd_session和用户信息存入redis，并设置过期时间
        String key = WxCons.THIRD_SESSION_BEGIN + ":" + thirdSessionKey;
        redisUtils.setEx(key, JSON.toJSONString(thirdSession), WxCons.TIME_OUT_SESSION, TimeUnit.HOURS);
        wxUser.setSessionKey(thirdSessionKey);
        return wxUser;
    }

    @Override
    public WxUser getByOpenId(String openId) {
        return this.baseMapper.selectOne(Wrappers.<WxUser>lambdaQuery()
                .eq(WxUser::getOpenId, openId));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRemark(String id, String remark) {
        WxUser user = this.getById(id);
        ApiAssert.notNull(ErrorCodeEnum.BAD_SELECT_FAILURE, user);
        String openId = user.getOpenId();
        WxUser updateWxUser = new WxUser();
        updateWxUser.setId(id);
        updateWxUser.setRemark(remark);
        ApiAssert.isTrue(ErrorCodeEnum.BAD_UPDATE_FAILURE, this.updateById(updateWxUser));
    }


}
